﻿using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using ST.Buz.Base;
using ST.Buz.Base.Entity;
using ST.Common.Util;
using ST.Common.Util.Model;
using ST.Common.Util.Mvc;
using System;
using System.Collections.Generic;
using Microsoft.Data.SqlClient;
using System.Linq;

namespace ST.Buz.Service
{
    public partial interface IServiceSysArea
    {
        /// <summary>
        /// 获取指定地区及其所有下级地区的树节点数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        List<TreeItem> GetChildrenTreeData(int id);

        /// <summary>
        /// 获取全部地区的树节点数据
        /// </summary>
        /// <returns></returns>
        List<TreeItem> GetTreeData();

        /// <summary>
        /// 获取指定地区及其所有下级地区的树节点数据的简单格式
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        List<SimpleTreeItem> GetSimpleTreeData(int id);

        /// <summary>
        /// 获取全部地区的树节点数据的简单格式
        /// </summary>
        /// <returns></returns>
        List<SimpleTreeItem> GetSimpleTreeData();

        /// <summary>
        /// 获取指定地区及其所有下级地区的树节点数据的ZTree格式
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        List<ZTreeItem> GetZTreeData(int id);

        /// <summary>
        /// 获取全部地区的树节点数据的ZTree格式
        /// </summary>
        /// <returns></returns>
        List<ZTreeItem> GetZTreeData();

        /// <summary>
        /// 删除地区
        /// </summary>
        /// <param name="id"></param>
        /// <param name="sessionCurrent"></param>
        /// <returns></returns>
        bool Delete(int id, UserSession sessionCurrent);

        /// <summary>
        /// 获取自身及所有下级节点ID
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        List<int> GetChildren(int id);

        /// <summary>
        /// 根据id获取详细信息
        /// </summary>
        Sys_Area GetDetail(int id, UserSession sessionCurrent);

        /// <summary>
        /// 新增或修改信息
        /// </summary>
        /// <param name="model"></param>
        /// <param name="sessionCurrent"></param>
        /// <returns></returns>
        int AddOrUpdate(Sys_Area model, UserSession sessionCurrent);

        /// <summary>
        /// 修改父节点
        /// </summary>
        bool UpdateParent(int id, int parentID, UserSession sessionCurrent);

        /// <summary>
        /// 修改排序
        /// </summary>
        bool UpdateOrder(SortItem[] items, UserSession sessionCurrent);

        /// <summary>
        /// 根据id获取最顶级名称
        /// </summary>
        /// <param name="id"></param>
        /// <param name="sessionCurrent"></param>
        /// <returns></returns>
        string GetTopLevelName(int id, UserSession sessionCurrent);
    }

    public partial class ServiceSysArea
    {
        private readonly IServiceSysLog serviceSysLog;

        public ServiceSysArea(BuzContext ctx,
            IServiceSysLog _serviceSysLog,
            ILogger<ServiceSysArea> log)
        {
            serviceSysLog = _serviceSysLog;
            context = ctx;
            logger = log;
        }

        /// <summary>
        /// 获取指定地区及其所有下级区域的树节点数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public List<TreeItem> GetChildrenTreeData(int id)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 获取全部地区的树节点数据
        /// </summary>
        /// <returns></returns>
        public List<TreeItem> GetTreeData()
        {
            throw new NotImplementedException();
        }

        protected List<Sys_Area> GetTree(int id)
        {
            SqlParameter[] parameters = new SqlParameter[]{
                    new SqlParameter("@area_id", id),
                    new SqlParameter("@errcode",System.Data.SqlDbType.Int),
                    new SqlParameter("@errmsg",System.Data.SqlDbType.NVarChar,200)
                };
            parameters[parameters.Length - 2].Direction = System.Data.ParameterDirection.Output;
            parameters[parameters.Length - 1].Direction = System.Data.ParameterDirection.Output;
            var result = context.SysArea.FromSqlRaw("sp_sys_area_tree @area_id,@errcode output,@errmsg output", parameters).ToList();
            if ((int)parameters[parameters.Length - 2].Value != 0)
            {
                throw new BuzException(Convert.ToString(parameters[parameters.Length - 1].Value));
            }
            return result;
        }

        /// <summary>
        /// 获取指定地区及其所有下级区域的树节点数据的简单格式
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public List<SimpleTreeItem> GetSimpleTreeData(int id)
        {
            try
            {
                var treeData = GetTree(id);
                var result = new List<SimpleTreeItem>();
                foreach (var q in treeData)
                {
                    result.Add(new SimpleTreeItem()
                    {
                        pId = q.PID.ToString(),
                        id = q.ID.ToString(),
                        key = q.ID.ToString(),
                        value = q.ID.ToString(),
                        title = q.Name,
                        rank = q.Sort
                    });
                }
                return result;
            }
            catch (BuzException ex)
            {
                logger.LogError(ex.InnerException ?? ex, ex.Message);
                throw ex;
            }
            catch (Exception ex)
            {
                logger.LogError(ex.InnerException ?? ex, ex.Message);
                throw new BuzException(ex.Message, ex);
            }
        }

        /// <summary>
        /// 获取全部地区的树节点数据的简单格式
        /// </summary>
        /// <returns></returns>
        public List<SimpleTreeItem> GetSimpleTreeData()
        {
            var query = from m in context.SysArea
                        select new SimpleTreeItem()
                        {
                            pId = m.PID.ToString(),
                            id = m.ID.ToString(),
                            key = m.ID.ToString(),
                            value = m.ID.ToString(),
                            title = m.Name,
                        };
            return query.ToList();
        }

        /// <summary>
        /// 获取指定地区及其所有下级区域的树节点数据的ZTree格式
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public List<ZTreeItem> GetZTreeData(int id)
        {
            try
            {
                var result = new List<ZTreeItem>();
                result.Add(new ZTreeItem()
                {
                    id = "0",
                    pId = "-1",
                    name = "全部",
                    code = "",
                    isParent = true,
                    open = true
                });
                var treeData = GetTree(id);
                foreach (var q in treeData)
                {
                    result.Add(new ZTreeItem()
                    {
                        pId = q.PID.ToString(),
                        id = q.ID.ToString(),
                        name = q.Name,
                        code = q.Code,
                        isParent = q.Children > 0,
                        open = true
                    });
                }
                return result;
            }
            catch (BuzException ex)
            {
                logger.LogError(ex.InnerException ?? ex, ex.Message);
                throw ex;
            }
            catch (Exception ex)
            {
                logger.LogError(ex.InnerException ?? ex, ex.Message);
                throw new BuzException(ex.Message, ex);
            }
        }

        /// <summary>
        /// 获取全部地区的树节点数据的ZTree格式
        /// </summary>
        /// <returns></returns>
        public List<ZTreeItem> GetZTreeData()
        {
            return GetZTreeData(0);
        }

        /// <summary>
        /// 删除具体操作
        /// </summary>
        /// <param name="id"></param>
        /// <param name="ip"></param>
        /// <param name="dtNow"></param>
        /// <param name="sessionCurrent"></param>
        protected void DeleteWithinTrans(int id, string ip, DateTime dtNow, UserSession sessionCurrent)
        {
            if (context.SysArea.Any(m => m.PID == id))
            {
                throw new BuzException("该地区有下级区域，请先删除下级区域后再删除");
            }
            if (context.SysOrganization.Any(m => m.AreaID == id))
            {
                throw new BuzException("该地区下有单位，请先删除单位后再删除");
            }
            var modelOld = Get(id, true);
            if (modelOld.Reserved)
            {
                throw new BuzException("系统预留，不能删除");
            }
            Delete(modelOld);

            serviceSysLog.Add(sessionCurrent, ip, $"删除地区{modelOld.Name}[{modelOld.Code}]信息，原信息：", modelOld, dtNow);
        }

        /// <summary>
        /// 删除地区
        /// </summary>
        /// <param name="id"></param>
        /// <param name="sessionCurrent"></param>
        /// <returns></returns>
        public bool Delete(int id, UserSession sessionCurrent)
        {
            bool success = false;
            try
            {
                //if (logger.IsEnabled(LogLevel.Debug))
                //{
                //	logger.LogDebug($"参数->id:{id}，state:{state}，remark:{remark}");
                //}
                if (sessionCurrent == null)
                {
                    throw new BuzException("用户会话不能为空");
                }

                using (var trans = context.Database.BeginTransaction())
                {
                    try
                    {
                        #region 事务具体操作
                        DateTime dtNow = DateTime.Now;
                        string ip = GetRequestIP();

                        DeleteWithinTrans(id, ip, dtNow, sessionCurrent);
                        #endregion

                        trans.Commit();
                    }
                    catch (Exception ex)
                    {
                        trans.Rollback();
                        throw ex.InnerException ?? ex;
                    }
                }

                success = true;
            }
            catch (BuzException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                logger.LogError(ex.InnerException ?? ex, "删除地区出错");
                throw new BuzException("删除地区失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
            }
            return success;
        }

        /// <summary>
        /// 获取自身及所有下级节点ID
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public List<int> GetChildren(int id)
        {
            if (id <= 0)
            {
                return null;
            }
            try
            {
                var children = context.ExecuteReader<TreeIdentity>(
                        "sp_sys_get_tree_children",
                        new SqlParameter[] { new SqlParameter("@id", id), new SqlParameter("@table_name", "Sys_Area") }
                    );
                if (children.Count == 0)
                {
                    return null;
                }
                List<int> lstTree = new List<int>();
                foreach (var c in children)
                {
                    lstTree.Add(c.ID);
                }
                return lstTree;
            }
            catch (BuzException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                logger.LogError(ex.InnerException ?? ex, "获取下级节点出错");
                throw new BuzException("获取下级节点失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
            }
        }

        /// <summary>
        /// 根据id获取详细信息
        /// </summary>
        public Sys_Area GetDetail(int id, UserSession sessionCurrent)
        {
            var query = from c in context.SysArea
                        join p in context.SysArea on c.PID equals p.ID into all
                        from a in all.DefaultIfEmpty()
                        where c.ID == id
                        select new Sys_Area()
                        {
                            ID = c.ID,
                            AddDate = c.AddDate,
                            AddManID = c.AddManID,
                            AddManName = c.AddManName,
                            Code = c.Code,
                            Name = c.Name,
                            PID = c.PID,
                            PName = a.Name,
                            PYCode = c.PYCode,
                            Reserved = c.Reserved,
                            Sort = c.Sort,
                            Visible = c.Visible
                        };
            var model = query.SingleOrDefault();
            return model;
        }

        /// <summary>
        /// 新增或修改信息
        /// </summary>
        public int AddOrUpdate(Sys_Area model, UserSession sessionCurrent)
        {
            try
            {
                if (model == null)
                {
                    throw new BuzException("参数不能为空");
                }
                if (model.ID > 0)
                {
                    var modelOld = Get(model.ID, true);
                    if (modelOld == null)
                    {
                        throw new BuzException("未找到相关记录");
                    }
                    if (modelOld.Reserved)
                    {
                        throw new BuzException("系统预留，不能修改");
                    }
                    Update(model);
                }
                else
                {
                    model.AddDate = DateTime.Now;
                    model.AddManID = sessionCurrent.UserID;
                    model.AddManName = sessionCurrent.UserName;
                    model.Visible = true;

                    model.ID = Add(model);
                }
                return model.ID;
            }
            catch (BuzException ex)
            {
                throw ex;
            }
            catch (DbUpdateException ex)
            {
                logger.LogError(ex.InnerException ?? ex, "保存对象信息出错");
                throw new BuzException("数据库保存失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
            }
            catch (Exception ex)
            {
                logger.LogError(ex.InnerException ?? ex, "保存对象信息出错");
                throw new BuzException("保存失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
            }
        }

        /// <summary>
        /// 修改父节点
        /// </summary>
        public bool UpdateParent(int id, int parentID, UserSession sessionCurrent)
        {
            try
            {
                if (id <= 0)
                {
                    throw new BuzException("参数不能为空");
                }
                var modelOld = context.SysArea.SingleOrDefault(m => m.ID == id);
                if (modelOld == null)
                {
                    throw new BuzException("未找到相关记录");
                }
                if (modelOld.Reserved)
                {
                    throw new BuzException("系统预留，不能修改");
                }
                if (parentID > 0)
                {
                    List<int> lstChildren = GetChildren(id);
                    if (lstChildren == null || lstChildren.Contains(parentID))
                    {
                        throw new BuzException("上级不存在或上级选择有误");
                    }
                }
                modelOld.PID = parentID;
                context.SaveChanges();

                return true;
            }
            catch (BuzException ex)
            {
                logger.LogError(ex.InnerException ?? ex, ex.Message);
                throw ex;
            }
            catch (Exception ex)
            {
                logger.LogError(ex.InnerException ?? ex, ex.Message);
                throw new BuzException(ex.Message, ex);
            }
        }

        /// <summary>
        /// 修改排序
        /// </summary>
        public bool UpdateOrder(SortItem[] items, UserSession sessionCurrent)
        {
            try
            {
                if (items == null || items.Length == 0)
                {
                    throw new BuzException("参数不能为空");
                }
                using (var trans = context.Database.BeginTransaction())
                {
                    try
                    {
                        foreach (SortItem item in items)
                        {
                            var entity = context.SysArea.Attach(new Sys_Area()
                            {
                                ID = item.id,
                                Sort = item.order
                            });
                            entity.Property("Sort").IsModified = true;
                            context.SaveChanges();
                        }
                        trans.Commit();

                        return true;
                    }
                    catch (Exception ex)
                    {
                        trans.Rollback();
                        throw ex.InnerException ?? ex;
                    }
                }
            }
            catch (BuzException ex)
            {
                logger.LogError(ex.InnerException ?? ex, "更新出错");
                throw ex;
            }
            catch (DbUpdateException ex)
            {
                logger.LogError(ex.InnerException ?? ex, "更新出错");
                throw new BuzException("更新失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
            }
            catch (ArgumentException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                logger.LogError(ex.InnerException ?? ex, "更新出错");
                throw new BuzException("更新失败，" + (ex.InnerException != null ? ex.InnerException.Message : ex.Message));
            }
        }

        /// <summary>
        /// 根据id获取最顶级名称
        /// </summary>
        /// <param name="id"></param>
        /// <param name="sessionCurrent"></param>
        /// <returns></returns>
        public string GetTopLevelName(int id, UserSession sessionCurrent)
        {
            SqlParameter[] parameters = new SqlParameter[]{
                    new SqlParameter("@area_id", id),
                    new SqlParameter("@top_level_name",System.Data.SqlDbType.NVarChar,800),
                    new SqlParameter("@errcode",System.Data.SqlDbType.Int),
                    new SqlParameter("@errmsg",System.Data.SqlDbType.NVarChar,200)
                };
            parameters[parameters.Length - 3].Direction = System.Data.ParameterDirection.Output;
            parameters[parameters.Length - 2].Direction = System.Data.ParameterDirection.Output;
            parameters[parameters.Length - 1].Direction = System.Data.ParameterDirection.Output;
            ExecuteNonQuery(context, "sp_sys_area_top_level_name", parameters, System.Data.CommandType.StoredProcedure);
            ////todo:不抛出异常
            //if ((int)parameters[parameters.Length - 2].Value != 0)
            //{
            //	throw new BuzException(Convert.ToString(parameters[parameters.Length - 1].Value));
            //}
            return Convert.ToString(parameters[parameters.Length - 3].Value);
        }
    }
}